home *** CD-ROM | disk | FTP | other *** search
/ CU Amiga Super CD-ROM 24 / CU Amiga Magazine's Super CD-ROM 24 (1998)(EMAP Images)(GB)(Track 1 of 2)[!][issue 1998-07].iso / CUCD / Magazine / C_Tutorial / Part-12 / dt0 / idcmp.c < prev    next >
C/C++ Source or Header  |  1998-05-04  |  11KB  |  416 lines

  1. #include "idcmp.h"
  2. #include "drawwin.h"
  3. #include "gadgets.h"
  4. #include "loadsave.h"
  5. #include "menu.h"
  6. #include "toolwin.h"
  7. #include "arexx.h"
  8. #include "fractal.h"
  9.  
  10. #include<dos/rdargs.h>
  11.  
  12. #include<string.h>
  13. #include<stdio.h>
  14.  
  15. #include<clib/dos_protos.h>
  16. #include<clib/exec_protos.h>
  17. #include<clib/gadtools_protos.h>
  18. #include<clib/graphics_protos.h>
  19. #include<clib/intuition_protos.h>
  20.  
  21. #define PROGRAM "HelloPainter"
  22. #define VERSION "11.4"
  23.  
  24. static UBYTE* VersionString = "\0$VER: " PROGRAM " " VERSION;
  25.  
  26. static void doGadgetUp(struct Window*, UWORD, struct Gadget*);
  27. static int  doMenuPick(struct Window*, UWORD);
  28. static int  doARexx(struct RexxMsg*, struct Window*);
  29.  
  30. static void new(struct Window*);
  31.  
  32. static int  isCommand(char*, char*, char*, LONG*);
  33. static void freeCommand(void);
  34.  
  35. /* Our message handling code */
  36. void handleIDCMP()
  37. {
  38.     char* text = "Hello World!";
  39.     int going = TRUE;
  40.     int drawing = FALSE;
  41.     ULONG drawsig, toolsig, arexxsig, gotsig;
  42.     struct Window* drawwin = getDrawWin();
  43.     drawsig = 1 << drawwin->UserPort->mp_SigBit;
  44.     arexxsig = getARexxSig();
  45.     while(going)
  46.     {
  47.         struct IntuiMessage* intuimsg;
  48.         /* Only include tool window signal mask if window is open */
  49.         toolsig = getToolSig();
  50.         /* Wait for messages to arrive */
  51.         gotsig = Wait(drawsig | toolsig | arexxsig);
  52.         /* Messages have arrived: loop through all of them */
  53.         /* Check messages from the drawing window first */
  54.         if(gotsig & drawsig)
  55.         {
  56.             while(intuimsg = GT_GetIMsg(drawwin->UserPort))
  57.             {
  58.                 /* Copy the important bits of the message */
  59.                 ULONG class = intuimsg->Class;
  60.                 UWORD code = intuimsg->Code;
  61.                 WORD mousex = intuimsg->MouseX;
  62.                 WORD mousey = intuimsg->MouseY;
  63.                 /* Reply when finished copying bits from message */
  64.                 GT_ReplyIMsg(intuimsg);
  65.                 /* Act on this message... */
  66.                 switch(class)
  67.                 {
  68.                 case IDCMP_MOUSEBUTTONS:
  69.                     switch(code)
  70.                     {
  71.                     case SELECTDOWN:
  72.                         drawing = TRUE;
  73.                         break;
  74.                     case SELECTUP:
  75.                         drawing = FALSE;
  76.                         break;
  77.                     }
  78.                     /* break; omitted so we draw on click, too */
  79.                 case IDCMP_MOUSEMOVE:
  80.                     if(drawing)
  81.                     {
  82.                         Move(drawwin->RPort, mousex, mousey);
  83.                         Text(drawwin->RPort, text, strlen(text));
  84.                         setModified(TRUE);
  85.                     }
  86.                     break;
  87.                 case IDCMP_MENUPICK:
  88.                     going = doMenuPick(drawwin, code);
  89.                     drawwin = getDrawWin();
  90.                     drawsig = 1 << drawwin->UserPort->mp_SigBit;
  91.                     break;
  92.                 }
  93.             }
  94.         }
  95.         /* Now check messages from the tool window */
  96.         if(going && (gotsig & toolsig))
  97.         {
  98.             struct Window* toolwin = getToolWin();
  99.             while(toolwin && (intuimsg = GT_GetIMsg(toolwin->UserPort)))
  100.             {
  101.                 /* Copy the important bits of the message */
  102.                 ULONG class = intuimsg->Class;
  103.                 UWORD code = intuimsg->Code;
  104.                 APTR iaddr = intuimsg->IAddress;
  105.                 if(class == IDCMP_IDCMPUPDATE)
  106.                     printf("Tool\n");
  107.                 /* Reply when finished copying bits from message */
  108.                 GT_ReplyIMsg(intuimsg);
  109.                 /* Act on this message... */
  110.                 switch(class)
  111.                 {
  112.                 case IDCMP_CLOSEWINDOW:
  113.                     closeToolWin();
  114.                     /* Update our local toolwin, so we stop loop */
  115.                     toolwin = NULL;
  116.                     uncheckToolBar(drawwin);
  117.                     break;
  118.                 case IDCMP_REFRESHWINDOW:
  119.                     /* You *MUST* remember to ask for and handle these refresh messages */
  120.                     GT_BeginRefresh(toolwin);
  121.                     GT_EndRefresh(toolwin, TRUE);
  122.                     break;
  123.                 case IDCMP_GADGETUP:
  124.                     doGadgetUp(drawwin, code, (struct Gadget*)iaddr);
  125.                     break;
  126.                 case IDCMP_MENUPICK:
  127.                     going = doMenuPick(drawwin, code);
  128.                     /* Update our local toolwin, so we stop loop */
  129.                     toolwin = getToolWin();
  130.                     drawwin = getDrawWin();
  131.                     drawsig = 1 << drawwin->UserPort->mp_SigBit;
  132.                     break;
  133.                 }
  134.             }
  135.         }
  136.         /* Now check messages from the ARexx port */
  137.         if(going && (gotsig & arexxsig))
  138.         {
  139.             struct RexxMsg* msg;
  140.             while(going && (msg = getARexxMsg()))
  141.                 going = doARexx(msg, drawwin);
  142.         }
  143.     }
  144. }
  145.  
  146. /* Process IDCMP_GADGETUP event */
  147. static void doGadgetUp(struct Window* drawwin, UWORD code, struct Gadget* gad)
  148. {
  149.     switch(gad->GadgetID)
  150.     {
  151.     case MYBUT_ID:
  152.         /* Our button was clicked!  Set foreground to next pen colour */
  153.         nextFgPen(drawwin);
  154.         break;
  155.     case MYPAL_ID:
  156.         /* Our palette gadget was clicked!  Set foreground to gadget colour */
  157.         setFgPen(drawwin, code);
  158.         break;
  159.     }
  160. }
  161.  
  162. /* Process IDCMP_MENUPICK event */
  163. static int doMenuPick(struct Window* drawwin, UWORD code)
  164. {
  165.     UWORD menuCode, menuNumber, itemNumber;
  166.     /* Loop over all the menu selections in the menu code */
  167.     struct MenuItem* item;
  168.     for(menuCode = code;
  169.             menuCode != MENUNULL;
  170.             menuCode = item->NextSelect)
  171.     {
  172.         item = ItemAddress(drawwin->MenuStrip, menuCode);
  173.         /* Extract the menu number and menu item number from the menu code */
  174.         menuNumber = MENUNUM(menuCode);
  175.         itemNumber = ITEMNUM(menuCode);
  176.         /* Now decide what to do based on what menu item was selected */
  177.         switch(menuNumber)
  178.         {
  179.         case 0:  /* Project menu */
  180.             switch(itemNumber)
  181.             {
  182.             case 0:  /* Load */
  183.                 {
  184.                     struct EasyStruct myreq = { sizeof(struct EasyStruct),
  185.                                                                             0,
  186.                                                                             "Overwrite Confirmation",
  187.                                                                             "Do you really wish to overwrite the current image?",
  188.                                                                             "Yes|No" };
  189.                     /* If the image isn't modified we don't need to ask... */
  190.                     if(!isModified() || EasyRequest(drawwin, &myreq, NULL))
  191.                     {
  192.                         return load();
  193.                     }
  194.                 }
  195.                 break;
  196.             case 1:  /* Save */
  197.                 save();
  198.                 break;
  199.             case 3:  /* New (item 2 is the bar!) */
  200.                 {
  201.                     struct EasyStruct myreq = { sizeof(struct EasyStruct),
  202.                                                                             0,
  203.                                                                             "Erase Confirmation",
  204.                                                                             "Do you really wish to clear the current image?",
  205.                                                                             "Yes|No" };
  206.                     /* If the image isn't modified we don't need to ask... */
  207.                     if(!isModified() || EasyRequest(drawwin, &myreq, NULL))
  208.                     {
  209.                         new(drawwin);
  210.                     }
  211.                 }
  212.                 break;
  213.             case 5:  /* About (item 4 is the bar!) */
  214.                 {
  215.                     struct EasyStruct myreq = { sizeof(struct EasyStruct),
  216.                                                                             0,
  217.                                                                             "About",
  218.                                                                             PROGRAM " v" VERSION "\n"
  219.                                                                                 "Brought to you by CU Amiga",
  220.                                                                             "OK" };
  221.                     EasyRequest(drawwin, &myreq, NULL);
  222.                 }
  223.                 break;
  224.             case 7:  /* Quit (item 6 is the bar!) */
  225.                 {
  226.                     struct EasyStruct myreq = { sizeof(struct EasyStruct),
  227.                                                                             0,
  228.                                                                             "Exit Confirmation",
  229.                                                                             "Do you really wish to quit?",
  230.                                                                             "Yes|No" };
  231.                     /* If the image isn't modified we don't need to ask... */
  232.                     if(!isModified() || EasyRequest(drawwin, &myreq, NULL))
  233.                         return FALSE;
  234.                 }
  235.                 break;
  236.             }
  237.             break;
  238.         case 1:  /* Pen menu */
  239.             switch(itemNumber)
  240.             {
  241.             case 0:  /* Next */
  242.                 nextFgPen(drawwin);
  243.                 break;
  244.             case 1:  /* Prev */
  245.                 prevFgPen(drawwin);
  246.                 break;
  247.             case 3:  /* Reset (item 2 is the bar!) */
  248.                 resetFgPen(drawwin);
  249.                 break;
  250.             }
  251.             break;
  252.         case 2:  /* Tools menu */
  253.             switch(itemNumber)
  254.             {
  255.             case 0:  /* Screen Bar */
  256.                 ShowTitle(drawwin->WScreen, item->Flags & CHECKED);
  257.                 break;
  258.             case 1:  /* Tool Bar */
  259.                 /* Do the open or close */
  260.                 if(item->Flags & CHECKED)
  261.                 {
  262.                     /* If the open fails, stop immediately */
  263.                     if(!openToolWin())
  264.                         return FALSE;
  265.                 }
  266.                 else
  267.                     closeToolWin();
  268.                 break;
  269.             case 3:  /* Fractal (item 2 is the bar!) */
  270.                 drawFractal(drawwin);
  271.             }
  272.         }
  273.     }
  274.     /* Keep going */
  275.     return TRUE;
  276. }
  277.  
  278. static void new(struct Window* win)
  279. {
  280.     SetRast(win->RPort, 0);
  281.     setModified(FALSE);
  282. }
  283.  
  284. /* Our RDArgs structure for use with ReadArgs() */
  285. static struct RDArgs* myrdargs = NULL;
  286.  
  287. int createArgs()
  288. {
  289.     if(myrdargs = AllocDosObject(DOS_RDARGS, NULL))
  290.     {
  291.         /* Disable prompting on stdin when "?" is the argument */
  292.         myrdargs->RDA_Flags = RDAF_NOPROMPT;
  293.         return TRUE;
  294.     }
  295.     else
  296.         printf("Error: could not allocate args for ARexx commands\n");
  297.     return FALSE;
  298. }
  299.  
  300. void freeArgs()
  301. {
  302.     if(myrdargs)
  303.         FreeDosObject(DOS_RDARGS, myrdargs);
  304. }
  305.  
  306. /* The result of a ReadArgs() while parsing commands */
  307. static struct RDArgs* rdargs = NULL;
  308.  
  309. /* Test if a string matches a command, using ReadArgs() */
  310. static int isCommand(char* text, char* comm,
  311.                                          char* templ, LONG* args)
  312. {
  313.     int clen = strlen(comm);
  314.     if(strnicmp(text, comm, clen) == 0)
  315.     {
  316.         /* Is the command followed by some whitespace? */
  317.         if(text[clen] == ' ' || text[clen] == '\t')
  318.         {
  319.             int tlen = strlen(text);
  320.             /* Set up our myrdargs so we can use ReadArgs() */
  321.             myrdargs->RDA_Source.CS_Buffer = text+clen+1;
  322.             myrdargs->RDA_Source.CS_Length = tlen-clen;
  323.             myrdargs->RDA_Source.CS_CurChr = 0;
  324.             myrdargs->RDA_DAList = NULL;
  325.             myrdargs->RDA_Buffer = NULL;
  326.             /* Temporarily end the string with a return... */
  327.             /* (Needed to get ReadArgs() to work properly) */
  328.             text[tlen] = '\n';
  329.             rdargs = ReadArgs(templ, args, myrdargs);
  330.             /* ... now we must reinstate the string's terminator */
  331.             text[tlen] = '\0';
  332.             return rdargs != NULL;
  333.         }
  334.     }
  335.     return NULL;
  336. }
  337.  
  338. static void freeCommand()
  339. {
  340.     if(rdargs)
  341.     {
  342.         FreeArgs(rdargs);
  343.         rdargs = NULL;
  344.     }
  345. }
  346.  
  347. /* The maximum number of arguments for our commands */
  348. #define MAX_ARGS (3)
  349.  
  350. #define COMM_QUIT        "QUIT"
  351.  
  352. #define COMM_NEW        "NEW"
  353.  
  354. #define COMM_PEN        "PEN"
  355. #define TEMPL_PEN        "PEN/N"
  356. enum PEN_ARGS { PEN_PEN };
  357.  
  358. #define COMM_DRAW        "DRAW"
  359. #define TEMPL_DRAW    "X/N,Y/N,TEXT/F"
  360. enum DRAW_ARGS { DRAW_X, DRAW_Y, DRAW_TEXT };
  361.  
  362. /* Process an ARexx message */
  363. static int doARexx(struct RexxMsg* msg, struct Window* drawwin)
  364. {
  365.     int going = TRUE;
  366.     /* By default, our reply will indicate an error */
  367.     LONG rc = 20;
  368.     char* res = NULL;
  369.     char* command = msg->rm_Args[0];
  370.     /* Parse the command */
  371.     if(stricmp(command, COMM_QUIT) == 0)
  372.     {
  373.         going = FALSE;
  374.         /* We recognised the command, so set rc to zero */
  375.         rc = 0;
  376.         res = "Hello Painter is quitting";
  377.     }
  378.     else if(stricmp(command, COMM_NEW) == 0)
  379.     {
  380.         new(drawwin);
  381.         rc = 0;
  382.         res = "Display cleared";
  383.     }
  384.     else
  385.     {
  386.         LONG args[MAX_ARGS];
  387.         int i;
  388.         for(i=0; i<MAX_ARGS; i++)
  389.             args[i] = NULL;
  390.         if(isCommand(command, COMM_PEN, TEMPL_PEN, args))
  391.          {
  392.             /* args[0] holds the pen number to use */
  393.             LONG* nptr = (LONG*)(args[PEN_PEN]);
  394.             setFgPen(drawwin, *nptr);
  395.             rc = 0;
  396.             res = "Pen set";
  397.         }
  398.         else if(isCommand(command, COMM_DRAW, TEMPL_DRAW, args))
  399.          {
  400.             /* args[DRAW_X] and args[DRAW_Y] hold the coordinate */
  401.             /* args[DRAW_TEXT] holds the text to be drawn */
  402.             LONG* xptr = (LONG*)(args[DRAW_X]);
  403.             LONG* yptr = (LONG*)(args[DRAW_Y]);
  404.             char* text = (char*)(args[DRAW_TEXT]);
  405.             Move(drawwin->RPort, *xptr, *yptr);
  406.             Text(drawwin->RPort, text, strlen(text));
  407.             setModified(TRUE);
  408.             rc = 0;
  409.             res = "Text drawn";
  410.         }
  411.         freeCommand();
  412.     }
  413.     replyARexxMsg(msg, rc, res);
  414.     return going;
  415. }
  416.